package drawables;



import java.awt.Color;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;

/**
 * 
 * @author David X. Wang
 *
 */
public class GaussianBlurFilter extends BoxBlurFilter {
	
	protected float[] kernelX, kernelY;
	
	public GaussianBlurFilter(){}
	
	public GaussianBlurFilter(int radiusX, int radiusY){
		setRadiusX(radiusX);
		setRadiusY(radiusY);
	}
	
	public void setRadiusX(int x){
		if(radiusX != x){
			radiusX = x;
			float sigma = radiusX/3f;
			kernelX = new float[radiusX*2 + 1];
			for(int i=0, j=-radiusX; i<kernelX.length; i++, j++)
				kernelX[i] = calcGaus(j, sigma);
		}
	}
	
	public void setRadiusY(int y){
		if(radiusY != y){
			radiusY = y;
			float sigma = radiusY/3f;
			kernelY = new float[radiusY*2 + 1];
			for(int i=0, j=-radiusY; i<kernelY.length; i++, j++)
				kernelY[i] = calcGaus(j, sigma);
		}
	}
	
	private float calcGaus(int x, float sigma){
		float term1 = (float)(1/(Math.sqrt(2*Math.PI*sigma*sigma)));
		float term2 = (float)Math.pow(Math.E, -((x*x)/(2*sigma*sigma)));
		return term1 * term2;
	}
	
	@Override
	protected Color averageColor(boolean horizontal, Color ... colors){
		float r = 0, g = 0, b = 0;
		float[] kernel = horizontal? kernelX : kernelY;
		for(int i=0; i<colors.length; i++){
			Color color = colors[i];
			r += color.getRed() * kernel[i];
			g += color.getGreen() * kernel[i];
			b += color.getBlue() * kernel[i];
		}
		if(r < 0) r = 0;
		else if(r > 255) r = 255;
		if(g < 0) g = 0;
		else if(g > 255) g = 255;
		if(b < 0) b = 0;
		else if(b > 255) b = 255;
		return new Color((int)r, (int)g, (int)b);
	}

	@Override
	public Rectangle2D getBounds2D(BufferedImage src) {
		return new Rectangle(src.getWidth(), src.getHeight());
	}

	@Override
	public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
		return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
	}

	@Override
	public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
		return null;
	}

	@Override
	public RenderingHints getRenderingHints() {
		return null;
	}

}
